#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <utility>
#include <tuple>
#include <ctime>

#include "DemoDictionary.h"

using namespace std;

void demoDictionaryLoop(void) {
    cout<<endl<<endl<<"demoDictionaryLoop"<<endl;
    
    map<string, int> monthDic{
        {"January",     31},
        {"February",    28},
        {"March",       31},
        {"April",       30},
        {"May",         31},
        {"June",        30},
        {"July",        31},
        {"August",      31},
        {"September",   30},
        {"October",     31},
        {"November",    30},
        {"December",    31},
    };
    
    map<string, int>  longMonthDic;
    map<string, int>  shortMonthDic;
    for (map<string, int>::iterator iter = monthDic.begin(); iter != monthDic.end(); iter++) {
        if (iter->second > 30) {
            longMonthDic[iter->first] = iter->second;
        } else {
            shortMonthDic[iter->first] = iter->second;
        }
    }
    
    for (auto iter : shortMonthDic) {
        cout<<iter.first<<" --> "<<iter.second<<endl;
    }
    
    for (auto iter : longMonthDic) {
        cout<<iter.first<<" --> "<<iter.second<<endl;
    }

}


// 如果是给 sort（升序排序）使用, 返回true, a 排在 b 前面
bool comp4PairSort(const pair<string,int> & a,const pair<string,int> & b) {
    if (a.first.length() == b.first.length()) {
        return a.first.compare(b.first);
    }
    return a.first.length() > b.first.length();
}

void demoDictionarySort(void) {
    cout<<endl<<endl<<"demoDictionarySort"<<endl;
    
//    map是STL的一个关联容器，以键值对存储的数据，其类型可以自己定义，每个关键字在map中只能出现一次，关键字不能修改，值可以修改；
//    map同set、multiset、multimap（与map的差别仅在于multimap允许一个键对应多个值）内部数据结构都是红黑树，而java中的hashmap是以hash table实现的。
//    所以map内部有序（自动排序，单词时按照字母序排序），查找时间复杂度为O(logn)
    
    map<string, int> monthDic{
        {"January",     31},
        {"February",    28},
        {"March",       31},
        {"April",       30},
        {"May",         31},
        {"June",        30},
        {"July",        31},
        {"August",      31},
        {"September",   30},
        {"October",     31},
        {"November",    30},
        {"December",    31},
    };
    
    for (auto iter : monthDic) {
        cout<<"map default sorted loop by key "<<iter.first<<" --> "<<iter.second<<endl;
    }
    
    // 键值对 构建为 vector
    vector<pair<string,int> > pairArr(monthDic.begin(), monthDic.end());
    
    // 按需排序
    sort(pairArr.begin(), pairArr.end(), comp4PairSort);
    
    for (auto iter : pairArr) {
        cout<<"sorted pairArr "<<iter.first<<" --> "<<iter.second<<endl;
    }
}

// 年月日 时分秒
typedef tuple<int, int, int, int, int, int> dateTimeTuple;

dateTimeTuple makeDTTupleFromTS(time_t ts=0) {
    if (ts <= 0) {
        ts = time(NULL);
    }
    
    cout <<"makeDTTupleFromTS, ts="<<ts<<endl;
    
    struct tm *tInfo = localtime(&ts);
//    struct tm {
//        int    tm_sec;        /* seconds after the minute [0-60] */
//        int    tm_min;        /* minutes after the hour [0-59] */
//        int    tm_hour;    /* hours since midnight [0-23] */
//        int    tm_mday;    /* day of the month [1-31] */
//        int    tm_mon;        /* months since January [0-11] */
//        int    tm_year;    /* years since 1900 */
//        int    tm_wday;    /* days since Sunday [0-6] */
//        int    tm_yday;    /* days since January 1 [0-365] */
//        int    tm_isdst;    /* Daylight Savings Time flag */
//        long    tm_gmtoff;    /* offset from UTC in seconds */
//        char    *tm_zone;    /* timezone abbreviation */
//    };
    dateTimeTuple rtn(tInfo->tm_year+1900, tInfo->tm_mon+1, tInfo->tm_mday, tInfo->tm_hour, tInfo->tm_min, tInfo->tm_sec);
    return rtn;
}

time_t makeTsFromDTTuple(const dateTimeTuple & dtTuple) {
    struct tm tInfo;
    tInfo.tm_zone = NULL;
    tInfo.tm_gmtoff = 0;
    tInfo.tm_isdst = -1;
    
    int year,month,day,hour,minute,second;
    tie(year,month,day,hour,minute,second) = dtTuple;
    
    tInfo.tm_year = year-1900;
    tInfo.tm_mon = month-1;
    tInfo.tm_mday = day;
    tInfo.tm_hour = hour;
    tInfo.tm_min = minute;
    tInfo.tm_sec = second;
    
    time_t ts = mktime(&tInfo);
     
    return ts;
}

// http://c.biancheng.net/view/8600.html
void demoTuple(void) {
    cout<<endl<<endl<<"demoTuple"<<endl;
    
    int size;
    //创建一个 tuple 对象存储 10 和 'x'
    tuple<int, char> mytuple(10, 'x');
    
    //计算 mytuple 存储元素的个数
    size = tuple_size<decltype(mytuple)>::value;
    
    //输出 mytuple 中存储的元素
    cout <<"demoTuple, mytuple 0=  "<< get<0>(mytuple) << " , mytuple 1= " << get<1>(mytuple) << endl;
    
    //修改指定的元素
    get<0>(mytuple) = 100;
    cout <<"demoTuple, mytuple 0= "<< get<0>(mytuple) << endl;
    
    //使用 makde_tuple() 创建一个 tuple 对象
    auto bar = make_tuple("test", 3.1, 14);
   
    //拆解 bar 对象，分别赋值给 mystr、mydou、myint
    const char* mystr = nullptr;
    double mydou;
    int myint;
    //使用 tie() 时，如果不想接受某个元素的值，实参可以用 ignore 代替
    tie(mystr, mydou, myint) = bar;
    //tie(ignore, ignore, myint) = bar;  //只接收第 3 个整形值
    
    //将 mytuple 和 bar 中的元素整合到 1 个 tuple 对象中
    auto mycat = tuple_cat(mytuple, bar);
    size = tuple_size<decltype(mycat)>::value;
    cout <<"demoTuple, mycat size="<< size << endl;
    
    //
    dateTimeTuple dtTuple = makeDTTupleFromTS();
    
    size = tuple_size<decltype(dtTuple)>::value;
    cout <<"demoTuple, dtTuple size="<< size << endl;
    
    //for (int i=0; i< size; ++i) {
        cout <<0<<":"<< get<0>(dtTuple) <<endl;
        cout <<1<<":"<< get<1>(dtTuple) <<endl;
        cout <<2<<":"<< get<2>(dtTuple) <<endl;
        cout <<3<<":"<< get<3>(dtTuple) <<endl;
        cout <<4<<":"<< get<4>(dtTuple) <<endl;
        cout <<5<<":"<< get<5>(dtTuple) <<endl;
    //}
    
    int year,month,day,hour,minute,second;
    tie(year,month,day,hour,minute,second) = dtTuple;
    cout <<"demoTuple, year "<< year<<", month "<< month<<", day "<< day<<", hour "<< hour<<", minute "<< minute<<", second "<< second << endl;
    
    time_t ts = makeTsFromDTTuple(dtTuple);
    cout <<"demoTuple, makeTsFromDTTuple return ts="<<ts<<endl;
}
